<?php

/**
 * 
 * ClientEngage: ClientEngage Visitor Voice (http://www.clientengage.com)
 * Copyright 2012, ClientEngage (http://www.clientengage.com)
 *
 * You must have purchased a valid license from CodeCanyon in order to have 
 * the permission to use this file.
 * 
 * You may only use this file according to the respective licensing terms 
 * you agreed to when purchasing this item on CodeCanyon.
 * 
 * 
 * 
 *
 * @author          ClientEngage <contact@clientengage.com>
 * @copyright       Copyright 2013, ClientEngage (http://www.clientengage.com)
 * @link            http://www.clientengage.com ClientEngage
 * @since           ClientEngage - Visitor Voice v 1.0
 * 
 */
App::uses('AppModel', 'Model');

/**
 * Visitorvoice Model
 *
 * @property Visitorform $Visitorform
 * @property Response $Response
 */
class Visitorvoice extends AppModel
{

    public $name = 'Visitorvoice';

    /**
     * belongsTo associations
     *
     * @var array
     */
    public $belongsTo = array(
        'Visitorform' => array(
            'className' => 'Visitorform',
            'foreignKey' => 'visitorform_id',
            'counterCache' => true,
            'conditions' => '',
            'fields' => '',
            'order' => ''
        )
    );

    /**
     * hasMany associations
     *
     * @var array
     */
    public $hasMany = array(
        'Response' => array(
            'className' => 'Response',
            'foreignKey' => 'visitorvoice_id',
            'dependent' => true,
            'conditions' => '',
            'fields' => '',
            'order' => '',
            'limit' => '',
            'offset' => '',
            'exclusive' => '',
            'finderQuery' => '',
            'counterQuery' => ''
        )
    );

    public function beforeSave($options = array())
    {
        $this->__deletedVisitorvoiceFormId = $this->field('visitorform_id');
        return parent::beforeSave($options);
    }

    public function afterSave($created)
    {
        if ($created == true)
        {
            $this->Visitorform->deleteFormCaches($this->field('visitorform_id'), false);
            $this->saveField('unique_id', $this->__getNextId());
        }


        parent::afterSave($created);
    }

    private $__deletedVisitorvoiceFormId = null;

    public function beforeDelete($cascade = true)
    {
        $this->__deletedVisitorvoiceFormId = $this->field('visitorform_id');
        return parent::beforeDelete($cascade);
    }

    public function afterDelete()
    {
        $this->Visitorform->deleteFormCaches($this->__deletedVisitorvoiceFormId, false);
        parent::afterDelete();
    }

    /**
     * Deletes the response cache of all visitorvoices of the given visitorform.
     * Used if a form or its fields are changed after the response collection 
     * has already commenced.
     * @param uuid $visitorform_id
     */
    public function deleteFormResponseCache($visitorform_id = null)
    {
        $this->updateAll(array('Visitorvoice.response_cache' => null), array('Visitorvoice.visitorform_id' => $visitorform_id));
    }

    /**
     * Checks if a given visitorform has any visitorvoices that are missing
     * their response cache
     * @param uuid $visitorform_id
     * @return bool True of there are any pending resposne caches
     */
    public function checkResponseCacheIncomplete($visitorform_id = null)
    {
        return $this->hasAny(array(
                    'Visitorvoice.response_cache' => null,
                    'Visitorvoice.visitorform_id' => $visitorform_id));
    }

    /**
     * Returns the count of visitorvoices which's response cache needs to be
     * re-generated
     * @param uuid $visitorform_id
     * @return int Number of response caches to be re-generated
     */
    public function countPendingResponseCache($visitorform_id = null)
    {
        return $this->find('count', array(
                    'conditions' => array(
                        'Visitorvoice.response_cache' => null,
                        'Visitorvoice.visitorform_id' => $visitorform_id),
        ));
    }

    /**
     * Regenerates the response cache of a visitorform in steps of 25 records
     * @param uuid $visitorform_id
     * @return bool Success
     */
    public function regenerateResponseCache($visitorform_id = null)
    {
        $unprocessed = $this->find('all', array(
            'limit' => 25,
            'fields' => array('id', 'response_cache'),
            'conditions' => array(
                'Visitorvoice.response_cache' => null,
                'Visitorvoice.visitorform_id' => $visitorform_id),
            'contain' => array(
                'Response' => array('fields' => array('id', 'field_id', 'value', 'field_option_id'),
                    'FieldOption' => array('fields' => array('id', 'title', 'position')),
                    'SelectedOption' => array('fields' => array('id', 'title', 'position')))
        )));

        foreach ($unprocessed as &$up)
        {
            $up['Visitorvoice']['response_cache'] = json_encode($up['Response']);
            unset($up['Response']);
        }
        return $this->saveAll($unprocessed);
    }

    /**
     * Saves the visitorvoice and stores the serialised responses for 
     * caching purposes
     * @param array $visitorvoice
     */
    public function saveVisitorvoice($visitorvoice = array())
    {
        if ($this->saveAll($visitorvoice))
        {
            $cachedVisitorvoice = $this->find('first', array(
                'conditions' => array('Visitorvoice.id' => $this->id),
                'contain' => array(
                    'Response' => array('fields' => array('id', 'field_id', 'value', 'field_option_id'),
                        'FieldOption' => array('fields' => array('id', 'title', 'position')),
                        'SelectedOption' => array('fields' => array('id', 'title', 'position')))
            )));

            $cachedVisitorvoice['Visitorvoice']['response_cache'] = json_encode($cachedVisitorvoice['Response']);
            $cachedVisitorvoice['Response'] = null;
            unset($cachedVisitorvoice['Response']);

            $this->save($cachedVisitorvoice);
        }
    }

    /**
     * Gets and deserialises all responses for a visitorform
     * @param uuid $visitorform_id
     * @return array Returns all responses for the given visitorform with a 
     * deserialised response cache
     */
    public function getResponseData($visitorform_id = null)
    {
        $options = array(
            'conditions' => array(
                'Visitorvoice.visitorform_id' => $visitorform_id
        ));

        $visitorvoices = $this->find('all', $options);

        foreach ($visitorvoices as &$up)
        {
            $up['Response'] = $this->__deserialise($up);
        }

        return $visitorvoices;
    }

    private function __deserialise(&$up)
    {
        $out = json_decode($up['Visitorvoice']['response_cache'], true);

        $up['Visitorvoice']['response_cache'] = null;
        unset($up['Visitorvoice']['response_cache']);

        return $out;
    }

    /**
     * Gets the next unique ID to be inserted into a visitorvoice
     * @return int Next unique ID
     */
    private function __getNextId()
    {
        $result = $this->find('first', array(
            'conditions' => array('Visitorvoice.visitorform_id' => $this->data['Visitorvoice']['visitorform_id']),
            'fields' => array('unique_id'),
            'limit' => 1,
            'order' => 'Visitorvoice.unique_id DESC'));


        if (isset($result['Visitorvoice']['unique_id']))
        {
            return((int) $result['Visitorvoice']['unique_id']) + 1;
        }
        else
            return 1;
    }

}
